Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Bcrypt algorithm support #1169

Merged
merged 14 commits into from
Apr 1, 2021

Conversation

seremenko-wish
Copy link
Contributor

@seremenko-wish seremenko-wish commented Mar 22, 2021

Related issue

#1137 @aeneasr

Proposed changes

  • New hashers.algorithm option in config to control password hashing algorithm. By default, the value is argon2. In order to use the Bcrypt hashing algorithm, bcrypt value should be used. Also, added a setting to control the cost for Bcrypt algorithm (hashers.bcrypt.cost) with default value 12.
  • Bcrypt algorithm truncates all input strings to 72 bytes, so a corresponding check was added
  • Tests for Bcrypt hasher

Checklist

  • I have read the contributing guidelines.
  • I have read the security policy.
  • I confirm that this pull request does not address a security
    vulnerability. If this pull request addresses a security. vulnerability, I
    confirm that I got green light (please contact
    [email protected]) from the maintainers to push
    the changes.
  • I have added tests that prove my fix is effective or that my feature
    works.
  • I have added or changed the documentation.

Further comments

  • Change of hashers.algorithmshould be considered a breaking change since passwords hashed by Argon2 won't be properly validated after this change. In order to handle this case properly, hashers should be separated from classes that check hashes. Should we create a separate issue for this?
  • Returning an error when a user tries to use very long password when the Bcrypt algorithm is active, seems like a user-friendly behavior. I would like to get feedback about this.

@CLAassistant
Copy link

CLAassistant commented Mar 22, 2021

CLA assistant check
All committers have signed the CLA.

@seremenko-wish seremenko-wish changed the title Bcrypt algorithm support feat: Bcrypt algorithm support Mar 22, 2021
@seremenko-wish seremenko-wish marked this pull request as ready for review March 22, 2021 23:46
Copy link
Member

@aeneasr aeneasr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for working on this, it looks good! One thing we need to take care of however is that we can't change the algorithm if we have users signed up already, as those users would no longer be able to log in.

This means that we need a password upgrade here: https:/ory/kratos/blob/master/selfservice/strategy/password/login.go#L149

The code for generating the password entry can be found at https:/ory/kratos/blob/master/selfservice/strategy/password/registration.go#L177-L196

It would probably also make sense to add a section about bcrypt here: https:/ory/kratos/blob/master/docs/docs/concepts/credentials/username-email-password.mdx

And lastly, it's actually fine by me if we use BCrypt per default, as the kratos-typical workloads are web based, meaning that Argon2 might underperform.

hash/hasher_bcrypt.go Outdated Show resolved Hide resolved
driver/config/config.go Outdated Show resolved Hide resolved
@seremenko-wish
Copy link
Contributor Author

Last commit fixes #1175

@seremenko-wish
Copy link
Contributor Author

seremenko-wish commented Mar 25, 2021

Thank you for working on this, it looks good! One thing we need to take care of however is that we can't change the algorithm if we have users signed up already, as those users would no longer be able to log in.

I separated the hash comparator from hashers, so changing of hashing algorithm won't prevent users from logging in.

This means that we need a password upgrade here: https:/ory/kratos/blob/master/selfservice/strategy/password/login.go#L149

fixed

The code for generating the password entry can be found at https:/ory/kratos/blob/master/selfservice/strategy/password/registration.go#L177-L196

this code does not need any changes as it uses the hasher specified in the configuration

It would probably also make sense to add a section about bcrypt here: https:/ory/kratos/blob/master/docs/docs/concepts/credentials/username-email-password.mdx

added

And lastly, it's actually fine by me if we use BCrypt per default, as the kratos-typical workloads are web based, meaning that Argon2 might underperform.

For backwards compatibility, I left Argon2id as the default hasher. We can create a separate task to make that switch in the future.

Copy link
Member

@zepatrik zepatrik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, this looks really good 👍

driver/config/.schema/config.schema.json Outdated Show resolved Hide resolved
driver/config/.schema/config.schema.json Show resolved Hide resolved
hash/hash_comparator.go Show resolved Hide resolved
// so if password is longer than 72 bytes, function returns an error
// See https://en.wikipedia.org/wiki/Bcrypt#User_input
if len(password) > 72 {
return errors.New("passwords are limited to a maximum length of 72 characters")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error will be passed down to the UI I guess. Please add it to the messages to allow translations and mapping to other text: https:/ory/kratos/blob/1940a679eb6b695e22cb939fb0d8d85cebb82a1e/text/message_registration.go

I guess you would then in the flow check for this error you return here similar to

a.Messages.Add(text.NewErrorValidationRegistrationFlowExpired(e.ago))

But maybe @aeneasr can give better pointers.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, it would be an error like this one (actually we can just add it do that file for now): https:/ory/kratos/blob/master/schema/errors.go#L59-L70

Copy link
Member

@aeneasr aeneasr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, just two tiny things but this is almost good to ship!

hash/hash_comparator.go Show resolved Hide resolved
// so if password is longer than 72 bytes, function returns an error
// See https://en.wikipedia.org/wiki/Bcrypt#User_input
if len(password) > 72 {
return errors.New("passwords are limited to a maximum length of 72 characters")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, it would be an error like this one (actually we can just add it do that file for now): https:/ory/kratos/blob/master/schema/errors.go#L59-L70

@seremenko-wish
Copy link
Contributor Author

Ok. Pushed an update! Pls take a look

Copy link
Member

@aeneasr aeneasr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, thank you! 🎉 Your contribution makes Ory better :)

@aeneasr
Copy link
Member

aeneasr commented Mar 31, 2021

The last thing is getting tests green - so running make format will resolve the one issue. The e2e tests have been failing for a while now on master so we need for someone to fix those first. I will probably not be able to do that this week :/

@aeneasr
Copy link
Member

aeneasr commented Mar 31, 2021

I have resolved the e2e tests so this should work again - rerunning tests now.

@seremenko-wish
Copy link
Contributor Author

ok. all checks are green now!

@aeneasr
Copy link
Member

aeneasr commented Apr 1, 2021

Awesome, thank you so much for your hard work!

@aeneasr aeneasr merged commit b2612ee into ory:master Apr 1, 2021
@seremenko-wish
Copy link
Contributor Author

@aeneasr would you want to add this feature to the next version release?

@aeneasr
Copy link
Member

aeneasr commented Apr 6, 2021

Yes, this is planned for 0.6

I am currently working on pushing out 0.6 this month!

@aeneasr
Copy link
Member

aeneasr commented May 25, 2021

Looks like OWASP is also not quite clear themselves as to which algorithm to support as they have recently updated their docs to encourage use of Argon2id whenever possible: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pre-hashing-passwords

@seremenko-wish
Copy link
Contributor Author

Yeah. That's fine. I saw that they recommend some argon2 settings. It would be interesting to measure performance with those settings.

btw, they encourage not to use any pre-hashing functions with bcrypt https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pre-hashing-passwords

@aeneasr
Copy link
Member

aeneasr commented May 25, 2021

Yes, thank you! I also saw that in a talk someone mentioned in another issue :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants